package main

import "fmt"

type Person struct {
	name string
	age  int
}

func main() {
	var p Person
	p.name = "Tom"
	p.age = 18
	println(p.name, p.age)   // Tom 18
	fmt.Printf("p=%v\n", p)  // p={Tom 18}
	fmt.Printf("p=%#v\n", p) // p=main.Person{name:"Tom", age:18}

	// 匿名结构体
	var p1 struct {
		Name string
		Age  int
	}
	p1.Name = "Tom"
	p1.Age = 18
	fmt.Printf("p1=%#v\n", p1) // p1=struct { Name string; Age int }{Name:"Tom", Age:18}

	// 创建指针类型结构体
	var p2 = new(Person)
	fmt.Printf("p2=%T\n", p2) // p2=*main.Person
	p2.name = "Tom"
	p2.age = 18
	fmt.Printf("p2=%#v\n", p2) // p2=&main.Person{name:"Tom", age:18}

	// 取结构体的地址实例化
	p3 := &Person{}
	fmt.Printf("p3=%T\n", p3)  // p3=*main.Person
	fmt.Printf("p3=%#v\n", p3) // p3=&main.Person{name:"", age:0}
	p3.name = "Tom"
	p3.age = 18
	fmt.Printf("p3=%#v\n", p3) // p3=&main.Person{name:"Tom", age:18}

	// 结构体初始化
	var p4 Person
	fmt.Printf("p4=%#v\n", p4) // p4=main.Person{name:"", age:0}

	// 使用键值对初始化
	p5 := &Person{
		name: "Tom",
		age:  18,
	}
	fmt.Printf("p5=%#v\n", p5) // p5=&main.Person{name:"Tom", age:18}
	// 使用值的列表初始化
	p6 := &Person{"Tom", 18}
	fmt.Printf("p6=%#v\n", p6)

	// 结构体内存布局
	type Student struct {
		name  string
		age   int
		score float32
	}
	s := Student{"Tom", 18, 90.0}
	fmt.Printf("s.name=%#v\n", &s.name)   // s.name=(*string)(0x14000136000)
	fmt.Printf("s.age=%#v\n", &s.age)     // s.age=(*int)(0x14000136010)
	fmt.Printf("s.score=%#v\n", &s.score) // s.score=(*float32)(0x14000136018)

	// 构造函数
	p7 := newPerson("Tom", 18)
	fmt.Printf("p7=%#v\n", p7) //  p7=&main.Person{name:"Tom", age:18}
	p8 := newPerson("aa", 12)
	p8.Dream() // aa want to be a 12
	p8.SetName("bb")
	fmt.Println(p8.name) // bb

	// 结构体到匿名字段
	s1 := Class{
		"Tom",
		18,
	}
	fmt.Printf("s1.name=%#v\n", s1.string) // s1.name="Tom"
	//  嵌套结构体
	u1 := User{
		"Tom",
		18,
		Address{"beijing", "chaoyang"},
		"123@qq.com",
	}
	fmt.Printf("u1.name=%#v\n", u1.name)
	var glass Glass
	glass.Name = "glass"
	glass.Address.province = "beijing"
	fmt.Printf("glass.province=%#v\n", glass.province)

}

type Class struct {
	string
	int
}

// 嵌套结构体
type Address struct {
	province string
	city     string
}
type User struct {
	name  string
	age   int
	addr  Address
	email string
}

// Glass 结构体匿名嵌套
type Glass struct {
	Name string
	Address
}

// 构造函数 所以该构造函数返回的是结构体指针类型。
func newPerson(name string, age int) *Person {
	return &Person{
		name: name,
		age:  age,
	}
}

func (p *Person) SetName(name string) {
	p.name = name
}

// Dream Person做梦的方法
func (p Person) Dream() {
	fmt.Printf("%s want to be a %d", p.name, p.age)
}
